/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : app_freertos.c
 * Description        : FreeRTOS applicative file
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "app_freertos.h"

#include "gpio.h"
#include "usart.h"
#include "spi.h"

#include "qspi_w25q64.h"

/* FatFs includes component */
#include "ff_gen_drv.h"
#include "sd_diskio.h"
#include "fatfs_app.h"
#include "cherryusb_app.h"

#include "cpost.h"
#include "cevent.h"

extern void lvgl_task(void *argument);


/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
    .name = "defaultTask",
    .priority = (osPriority_t)osPriorityLow,
    .stack_size = 256 * 2};

osThreadId_t user_task_handle;
const osThreadAttr_t user_task_attributes = {
    .name = "user_task",
    .priority = (osPriority_t)osPriorityNormal1,
    .stack_size = 256 * 4};

osThreadId_t lvgl_task_handle;
const osThreadAttr_t lvgl_task_attributes = {
    .name = "lvgl_task",
    .priority = (osPriority_t)osPriorityBelowNormal,
    .stack_size = 1024 * 12};


/* USER CODE END FunctionPrototypes */

/* USER CODE BEGIN 2 */
void vApplicationIdleHook(void)
{
    /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
    to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
    task. It is essential that code added to this hook function never attempts
    to block in any way (for example, call xQueueReceive() with a block time
    specified, or call vTaskDelay()). If the application makes use of the
    vTaskDelete() API function (as this demo application does) then it is also
    important that vApplicationIdleHook() is permitted to return to its calling
    function, because it is the responsibility of the idle task to clean up
    memory allocated by the kernel to any task that has since been deleted. */
}
/* USER CODE END 2 */

/* USER CODE BEGIN 1 */
/* Functions needed when configGENERATE_RUN_TIME_STATS is on */
__weak void configureTimerForRunTimeStats(void)
{
}

__weak unsigned long getRunTimeCounterValue(void)
{
    return 0;
}
/* USER CODE END 1 */

/* USER CODE BEGIN PREPOSTSLEEP */
__weak void PreSleepProcessing(uint32_t ulExpectedIdleTime)
{
    /* place for user code */
}

__weak void PostSleepProcessing(uint32_t ulExpectedIdleTime)
{
    /* place for user code */
}
/* USER CODE END PREPOSTSLEEP */

/**
 * @brief  FreeRTOS initialization
 * @param  None
 * @retval None
 */
void MX_FREERTOS_Init(void)
{
    /* creation of defaultTask */
    defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
    user_task_handle = osThreadNew(user_task, NULL, &user_task_attributes);
    lvgl_task_handle = osThreadNew(lvgl_task, NULL, &lvgl_task_attributes);
}

/**
 * @brief Function implementing the defaultTask thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
    osDelay(10);

    for (;;) {
        osDelay(1);
        flush_printf_buffer();
        cpostProcess();
    }
}

void user_task(void *argument)
{
    int count = 0;

    ceventInit();
    ceventPost(EVENT_INIT_STAGE2);
    //cpost(printf, "hello cpost.\r\n", 2000);

    OSPI_W25Qxx_Init();
    sd_fatfs_init();
    cherryusb_app_init();

    for (;;) {
        osDelay(1000);
    }
}
